using System.Collections.Generic;
using UnityEngine;

public class SwordController : MonoBehaviour
{
    private Animator anim;
    private PolygonCollider2D cc;
    private Rigidbody2D rb;
    Player player;

    bool canRotate = true;
    bool isReturning = false;
    private float returnSpeed = 10f;
    private float freezeTimeDuration;

    [Header("Bounce Info")]
    private bool isBouncing;
    private float bounceSpeed;
    private int amountBounce;
    private List<Transform> targets = new List<Transform>();
    private int targetIndex;

    [Header("Pierce info")]
    private float pierceAmount;

    [Header("Spin info")]
    private bool isSpinning;
    private bool wasStopped;
    private float spinTimer;
    private float maxTravelDistance;
    private float spinDuration;

    private float hitCooldown;
    private float hitTimer;

    private void Awake()
    {
        anim = GetComponentInChildren<Animator>();
        rb = GetComponent<Rigidbody2D>();
        cc = GetComponent<PolygonCollider2D>();
    }

    private void Update()
    {
        BasicLogic();
        BounceLogic();
        SpinLogic();
    }

    private void SpinLogic()
    {
        if (isSpinning && !isReturning)
        {
            if (Vector2.Distance(player.transform.position, transform.position) > maxTravelDistance && !wasStopped)
            {
                StopWhenSpinning();
            }

            if (wasStopped)
            {
                spinTimer -= Time.deltaTime;

                transform.position = Vector2.MoveTowards(transform.position, new Vector2(transform.position.x + 1, transform.position.y), 2.4f * Time.deltaTime);

                if (spinTimer < 0)
                {
                    isReturning = true;
                    isSpinning = false;
                }


                hitTimer -= Time.deltaTime;

                if (hitTimer < 0)
                {
                    hitTimer = hitCooldown;

                    Collider2D[] colliders = Physics2D.OverlapCircleAll(transform.position, 1);

                    foreach (var hit in colliders)
                    {
                        if (hit.GetComponent<Enemy>() != null)
                            SwordSkillDamage(hit.GetComponent<EnemyData>());
                    }
                }
            }
        }
    }

    private void StopWhenSpinning()
    {
        wasStopped = true;
        rb.constraints = RigidbodyConstraints2D.FreezePosition;
        spinTimer = spinDuration;
    }

    private void BounceLogic()
    {
        if (isBouncing && targets.Count > 0 && !isReturning)
        {
            transform.position = Vector2.MoveTowards(transform.position, targets[targetIndex].position - Vector3.down, bounceSpeed * Time.deltaTime);
            if (Vector2.Distance(transform.position, targets[targetIndex].position - Vector3.down) < .1f)
            {
                SwordSkillDamage(targets[targetIndex].GetComponent<EnemyData>());
                targetIndex++;
                amountBounce--;

                if (amountBounce < 0)
                {
                    isBouncing = false;
                    isReturning = true;
                }

                if (targetIndex >= targets.Count)
                {
                    targetIndex = 0;
                }
            }
        }
    }

    private void BasicLogic()
    {
        if (canRotate)
        {
            transform.right = rb.velocity;
        }
        if (isReturning)
        {
            anim.SetBool("Rotate", true);
            transform.position = Vector2.MoveTowards(transform.position, player.transform.position, returnSpeed * Time.deltaTime);
            if (Vector2.Distance(player.transform.position, transform.position) < 1)
            {
                player.CatchSword();
            }
        }
    }

    private void SwordSkillDamage(EnemyData enemy)
    {
        player.data.DoDamage(enemy);
        enemy.transform.GetComponent<Enemy>()?.StartCoroutine("FreezeTimerFor", freezeTimeDuration);
    }

    void DestroyMe()
    {
        Destroy(gameObject);
    }

    public void ReturnSword()
    {
        transform.parent = null;
        rb.constraints = RigidbodyConstraints2D.FreezeAll;
        isReturning = true;
    }

    public void SetupBounce(bool _isBouncing, int _amountOfBounces, float _bounceSpeed, float _freezeTimeDuration)
    {
        freezeTimeDuration = _freezeTimeDuration;
        isBouncing = _isBouncing;
        amountBounce = _amountOfBounces;
        bounceSpeed = _bounceSpeed;


        targets = new List<Transform>();
    }

    public void SetupPierce(int pierceAmount)
    {
        this.pierceAmount = pierceAmount;
    }

    public void SetupSpin(bool _isSpinning, float _maxTravelDistance, float _spinDuration, float _hitCooldown)
    {
        isSpinning = _isSpinning;
        maxTravelDistance = _maxTravelDistance;
        spinDuration = _spinDuration;
        hitCooldown = _hitCooldown;
    }

    public void SetSword(Vector2 dir, float gravityScale, Player p, float returnSpeed)
    {
        this.returnSpeed = returnSpeed;
        player = p;
        if (pierceAmount <= 0)
            anim.SetBool("Rotate", true);
        rb.velocity = dir;
        rb.gravityScale = gravityScale;
        Invoke("DestroyMe", 6f);
    }


    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (isReturning) return;
        if (collision.GetComponent<Enemy>() != null)
        {
            SwordSkillDamage(collision.GetComponent<EnemyData>());
            if (isBouncing && targets.Count <= 0)
            {
                Collider2D[] colliders = Physics2D.OverlapCircleAll(transform.position, 10);
                foreach (var hit in colliders)
                {
                    if (hit.GetComponent<Enemy>() != null)
                        targets.Add(hit.transform);
                }
            }
        }
        StopSword(collision);
    }

    private void StopSword(Collider2D collision)
    {
        if (pierceAmount > 0 && collision.GetComponent<Enemy>() != null)
        {
            pierceAmount--;
            return;
        }

        if (isSpinning)
        {
            StopWhenSpinning();
            return;
        }
        canRotate = false;
        cc.enabled = false;
        rb.bodyType = RigidbodyType2D.Kinematic;
        rb.constraints = RigidbodyConstraints2D.FreezeAll;

        if (isBouncing && targets.Count > 0) return;

        anim.SetBool("Rotate", false);
        transform.SetParent(collision.transform);

    }


}
